package com.sh.data.engine.application.service.datadev;

import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.sh.data.engine.application.model.dto.datadev.OfflineDevQualityFieldResponse;
import com.sh.data.engine.application.model.dto.datadev.OfflineDevQualityTableResponse;
import com.sh.data.engine.application.model.request.datadev.OfflineDevDataQualityRuleRequest;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.authority.service.DataAuthService;
import com.sh.data.engine.domain.base.model.UserContext;
import com.sh.data.engine.domain.dataasset.model.domain.TableInfoBizDomain;
import com.sh.data.engine.domain.dataasset.model.param.QueryTableParam;
import com.sh.data.engine.domain.dataasset.service.TableService;
import com.sh.data.engine.domain.datadev.offline.model.domain.OfflineDevDataQualityDetailDomain;
import com.sh.data.engine.domain.datadev.offline.model.enums.OfflineDevTaskStopEnum;
import com.sh.data.engine.domain.datadev.offline.model.param.OfflineDevDataQualityRuleParam;
import com.sh.data.engine.domain.datadev.offline.service.DatadevJobService;
import com.sh.data.engine.domain.datadev.offline.service.OfflineDevMenuNodeService;
import com.sh.data.engine.domain.dataquality.model.domain.DataQualityRuleTemplateDomain;
import com.sh.data.engine.domain.dataquality.model.domain.DataQualityTableInfoDomain;
import com.sh.data.engine.domain.dataquality.model.domain.RuleCondition;
import com.sh.data.engine.domain.dataquality.service.DataQualityManagerService;
import com.sh.data.engine.domain.integration.datasource.service.DataSourceService;
import com.sh.data.engine.domain.shims.db.model.FieldInfoDomain;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.domain.workspace.manager.model.domain.UserDomain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * @author: mengzheng.mhc
 * @date: 2025/9/11 9:15
 */
@Slf4j
@Service
public class OfflineDevDataQualityApplicationService {

    @Autowired
    private TableService tableService;

    @Autowired
    private DataAuthService dataAuthService;

    @Autowired
    private DataSourceService dataSourceService;

    @Autowired
    private OfflineDevMenuNodeService menuNodeService;

    @Autowired
    private DataQualityManagerService dataQualityManagerService;

    @Autowired
    private DatadevJobService datadevJobService;

    public List<OfflineDevQualityTableResponse> getTables() {
        Long projectId = ServletUtils.getProjectId();

        QueryTableParam param = new QueryTableParam();

        List<TableInfoBizDomain> tableList = tableService.getTableList(projectId, param);

        List<DataQualityTableInfoDomain> dataQualityTableInfoDomains = Lists.newArrayList();
        tableList.forEach(
            t -> {
                DataQualityTableInfoDomain domain = new DataQualityTableInfoDomain();
                domain.setTblId(t.getTblId());
                domain.setTblIdStr(t.getTblIdStr());
                domain.setTableName(t.getTableName());
                domain.setComment(t.getTableComment());
                domain.setHasPartition(t.isPartitionTable() ? 1 : 0);
                domain.setThemeId(t.getThemeId());
                // 设置这个表的权限 0-只读 1—读写 2-无读写权限 如果无读写权限，那么不能建立规则
                domain.setAccessMode(
                    dataAuthService.getTblAuth(projectId, UserContext.getUserId(), t.getTblId()));
                dataQualityTableInfoDomains.add(domain);
            });

        return ConvertUtil.copyProperties(
            dataQualityTableInfoDomains, OfflineDevQualityTableResponse.class);
    }

    public List<OfflineDevQualityFieldResponse> getFields(String tableName) {
        Long projectId = ServletUtils.getProjectId();

        List<FieldInfoDomain> fieldListProjectId =
            dataSourceService.getFieldListProjectId(tableName, projectId);

        return ConvertUtil.copyProperties(fieldListProjectId, OfflineDevQualityFieldResponse.class);
    }

    public List<DataQualityRuleTemplateDomain> getRuleTemplates(Integer templateTableType) {
        return dataQualityManagerService.getRuleTemplates(templateTableType);
    }

    public Boolean saveRule(OfflineDevDataQualityRuleRequest dataQualityRule) {
        Long projectId = ServletUtils.getProjectId();
        UserDomain userDomain = UserContext.getUserInfo();

        if (dataQualityRule.getRuleDiy() == 0) {

            String ruleCompareType = dataQualityRule.getRuleCompareType();
            if (StringUtils.isNotBlank(ruleCompareType) && dataQualityRule.getTemplateId() != 13) {
                int ruleCompareTypeSize = ruleCompareType.split(",").length;
                if (ruleCompareTypeSize > 2) {
                    throw new BusinessException("最多选择两个比较方式");
                }
                if (StringUtils.isNotBlank(dataQualityRule.getRuleCondition())) {
                    List<RuleCondition> ruleConditions =
                        JSONArray.parseArray(dataQualityRule.getRuleCondition(), RuleCondition.class);
                    String value = ruleConditions.get(0).getValue();
                    int valueSize = Arrays.asList(value.split(",")).size();
                    if (ruleCompareTypeSize != valueSize) {
                        throw new BusinessException("比较方式个数与期望值个数不匹配");
                    }
                }
            }

            if (dataQualityRule.getRuleType() == null) {
                throw new BusinessException("规则类型不能为空");
            }
            if (dataQualityRule.getTemplateId() == null) {
                throw new BusinessException("规则模版不能为空");
            }
        }
        OfflineDevDataQualityRuleParam offlineDevDataQualityRuleParam =
            ConvertUtil.copyProperties(dataQualityRule, OfflineDevDataQualityRuleParam.class);
        return menuNodeService.saveRule(offlineDevDataQualityRuleParam, projectId, userDomain);
    }

    public OfflineDevDataQualityDetailDomain getRule(Long nodeId) {
        return menuNodeService.getRule(nodeId);
    }

    public Long run(Long nodeId) {
        int execType = 0;
        Long projectId = ServletUtils.getProjectId();
        String userId = UserContext.getUserId();

        return datadevJobService.runRule(nodeId, execType, projectId, userId);
    }

    public Boolean stop(Long jobId) {
        datadevJobService.stopJob(jobId, OfflineDevTaskStopEnum.DATA_QUALITY.getCode());
        return true;
    }
}
